/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package CardGame;

import DataManager.DbManager;
import DataManager.MySQLCommonDataProvider;
import Service.CardConstant;
import java.util.ArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Nhan Nguyen
 */
class TienLenLogic {

    public static Logger log = LoggerFactory.getLogger(TienLenLogic.class.getName());

    public boolean checkCardOwnership(byte[] cards, GameTable gt, byte playerIndex) {

        TienLenService.logGame.debug("{}: {} danh "+CardUtils.cardsToString(cards),
                gt.tableID, gt.getJoinedPlayerAt(playerIndex));
//
//        System.out.print("Player cards: ");
//        for (int i=0; i<gt.cards[playerIndex].length; i++) System.out.print(gt.cards[playerIndex][i]+ " ");
//        log.info();

        int i, j;
        for (i = 0; i < cards.length; i++) {
            for (j = 0; j < gt.cards[playerIndex].length; j++) {
                if (cards[i] == gt.cards[playerIndex][j]) {
                    break;
                }
            }
            // cannot find some cards
            if (j == gt.cards[playerIndex].length) {
                return false;
            }
        }
        return true;
    }

    public int checkImmediateWin(GameTable gt) {
        int firstPlayerIndex = 0;
        int winType=0;
        boolean immediateWin = false;
        /**
         * Ván khởi đầu là ván chơi đầu tiên, hoặc ván bắt đầu chơi lại vì một lí do nào đó.
         * Trong ván này, ai sở hữu lá ♠3 (ba bích) thì được đánh trước nhưng bài đánh ra phải có lá này trong đó.
         * Nếu người sở hữu lá ♠3 (ba bích) mà có BA ĐÔI THÔNG 3-4-5 hoặc/và TỨ QUÝ 3 thì người đó tới trắng luôn.
         */
        if (gt.isFirstDeal && gt.isNewTurn) {
            for (int playerIndex = 0; playerIndex < gt.getNumberOfJoinedPlayers(); playerIndex++) {
                //Tứ quý 3
                if (((gt.cards[playerIndex][0] / 4) == (gt.cards[playerIndex][3] / 4)) &&
                        ((gt.cards[playerIndex][0] / 4)==3)) {
                    firstPlayerIndex = playerIndex;
                    immediateWin = true;
                    winType=CardConstant.AN_TRANG_BON_3;
                    TienLenService.logGame.debug("{}: Tu quy 3",gt.tableID);
                    break;
                }
            }
        }
        /**
         * Tứ quý heo
         */
        if(!immediateWin){
            for (int playerIndex = 0; playerIndex < gt.getNumberOfJoinedPlayers(); playerIndex++) {
            //Tứ quý heo về luôn
            /**
             * @todo:Có cấn check 3 bích không ta
             */
            if ((gt.cards[playerIndex][9]) == 60) {
                firstPlayerIndex = playerIndex;
                immediateWin = true;
                winType=CardConstant.AN_TRANG_BON_2;
                TienLenService.logGame.debug("{}: Tu quy heo", gt.tableID);
                break;
            }
            ArrayList firstList = new ArrayList();
            ArrayList secondList = new ArrayList();
            ArrayList thirdList = new ArrayList();
            ArrayList fourthList = new ArrayList();
            for (int i = 0; i < gt.cards[playerIndex].length; i++) {
                if (firstList.contains(gt.cards[playerIndex][i] / 4)) {
                    if (secondList.contains(gt.cards[playerIndex][i] / 4)) {
                        if (thirdList.contains(gt.cards[playerIndex][i] / 4)) {
                            fourthList.add(gt.cards[playerIndex][i] / 4);
                        } else {
                            thirdList.add(gt.cards[playerIndex][i] / 4);
                        }
                    } else {
                        secondList.add( gt.cards[playerIndex][i] / 4);
                    }
                } else {
                    firstList.add(gt.cards[playerIndex][i] / 4);
                }
            }
            /**
             * Sảnh rồng:Sảnh từ 3 đến 2
             */
            if (firstList.size() == 13) {
                firstPlayerIndex = playerIndex;
                immediateWin = true;
                winType=CardConstant.AN_TRANG_SANH_RONG;
                TienLenService.logGame.debug("{}: Sanh rong", gt.tableID);
                break;
            }
            /**
             * 6 đôi
             */
            if ((fourthList.size() + secondList.size()) == 6) {
                firstPlayerIndex = playerIndex;
                immediateWin = true;
                winType=CardConstant.AN_TRANG_6_DOI;
                TienLenService.logGame.debug("{}: 6 doi", gt.tableID);
                break;
            }
            /**
             * Ván đầu tiên,có 3 đôi thông 3-4-5 và 3 bích
             */
            if( (secondList.size() >=3)
                    && ((Integer)secondList.get(0) == 3)
                    && ((gt.cards[playerIndex][0]) == 12)
                    && gt.isNewTurn && gt.isFirstDeal)
            {

                boolean flag = true;
                if(gt.cards[playerIndex][0]!=12){
                    flag=false;
                }
                for (int i = 1; i <= 2; i++){
                    if ((Integer)secondList.get(i) - (Integer)secondList.get(i - 1) != 1){
                        flag = false;
                    }
                }
                if(flag){
                    firstPlayerIndex = playerIndex;
                    TienLenService.logGame.debug("{}: 3 doi thong 3-4-5 co 3 bich", gt.tableID);
                    immediateWin = true;
                    winType=CardConstant.AN_TRANG_3_DOI_THONG_3_BICH;
                    break;
                }
            }
            /**
             * 5 đôi thông
             */
             if (secondList.size() == 5)
            {
                boolean flag = true;
                for (int i = 1; i < secondList.size(); i++){
                    if (((Integer)secondList.get(i) - (Integer)secondList.get(i - 1)) != 1){
                         flag = false;
                    }
                }
                 if(flag){
                    firstPlayerIndex = playerIndex;
                    immediateWin = true;
                    winType=CardConstant.AN_TRANG_5_DOI_THONG;
                    TienLenService.logGame.debug("{}: 5 doi thong", gt.tableID);
                    break;
                }
            }
            }
        }

        if (immediateWin) {
//            MySQLCommonDataProvider dataManager = new MySQLCommonDataProvider();
            MySQLCommonDataProvider dataManager = DbManager.GetCommonDataManager();
            try {
                gt.playerResult[0] = gt.getJoinedPlayerAt(firstPlayerIndex);
                gt.playerBalance[0] = 0;
                int order = 1;
                for (int i = 0; i < gt.getNumberOfJoinedPlayers(); i++) {
                    if (i != firstPlayerIndex) {
                        gt.playerResult[order] = gt.getJoinedPlayerAt(i);
                        int playerMoney = dataManager.retrieveAccountBalance(gt.playerResult[order]);
                        gt.playerBalance[0] += Math.min(gt.betMoney*2, playerMoney);
                        gt.playerBalance[order] = Math.max(-gt.betMoney*2, -playerMoney);
                        order++;
                    }
                }
            } catch (Exception e) {
                log.error("Exception in checkImmediateWin", e.getMessage());
                e.printStackTrace();
                return winType;
            } finally {
                dataManager.closeConnection();
            }
        }
        return winType;
    }

//    public int checkImmediateWinDraf(GameTable gt) {
//        /**
//         * @TODO:xử lý trường hợp 2 người cùng tới trắng
//         */
//        int firstPlayerIndex = 0;
//        int winType=0;
//        boolean immediateWin = false;
//        ArrayList antrangList= new ArrayList();
//        /**
//         * Ván khởi đầu là ván chơi đầu tiên, hoặc ván bắt đầu chơi lại vì một lí do nào đó.
//         * Trong ván này, ai sở hữu lá ♠3 (ba bích) thì được đánh trước nhưng bài đánh ra phải có lá này trong đó.
//         * Nếu người sở hữu lá ♠3 (ba bích) mà có BA ĐÔI THÔNG 3-4-5 hoặc/và TỨ QUÝ 3 thì người đó tới trắng luôn.
//         */
//        if (gt.isNewTurn) {
//            for (int playerIndex = 0; playerIndex < gt.getNumberOfJoinedPlayers(); playerIndex++) {
//                //Tứ quý 3
//                if ((gt.cards[playerIndex][0] / 4) == (gt.cards[playerIndex][3] / 4)) {
//                    firstPlayerIndex = playerIndex;
//                    immediateWin = true;
//                    winType=CardConstant.AN_TRANG_BON_3;
//                    log.info("Tu quy 3");
//                    antrangList.add(playerIndex);
//                    //break;
//                }
//            }
//        }
//        /**
//         * Tứ quý heo
//         */
//        if(!immediateWin){
//            for (int playerIndex = 0; playerIndex < gt.getNumberOfJoinedPlayers(); playerIndex++) {
//            //Tứ quý heo về luôn
//            /**
//             * @todo:Có cấn check 3 bích không ta
//             */
//            if ((gt.cards[playerIndex][9]) == 60) {
//                firstPlayerIndex = playerIndex;
//                immediateWin = true;
//                winType=CardConstant.AN_TRANG_BON_2;
//                log.info("Tu quy heo");
//                break;
//            }
//            ArrayList firstList = new ArrayList();
//            ArrayList secondList = new ArrayList();
//            ArrayList thirdList = new ArrayList();
//            ArrayList fourthList = new ArrayList();
//            for (int i = 0; i < gt.cards[playerIndex].length; i++) {
//                if (firstList.contains(gt.cards[playerIndex][i] / 4)) {
//                    if (secondList.contains(gt.cards[playerIndex][i] / 4)) {
//                        if (thirdList.contains(gt.cards[playerIndex][i] / 4)) {
//                            fourthList.add(gt.cards[playerIndex][i] / 4);
//                        } else {
//                            thirdList.add(gt.cards[playerIndex][i] / 4);
//                        }
//                    } else {
//                        secondList.add( gt.cards[playerIndex][i] / 4);
//                    }
//                } else {
//                    firstList.add(gt.cards[playerIndex][i] / 4);
//                }
//            }
//            /**
//             * Sảnh rồng:Sảnh từ 3 đến 2
//             */
//            if (firstList.size() == 13) {
//                firstPlayerIndex = playerIndex;
//                immediateWin = true;
//                winType=CardConstant.AN_TRANG_SANH_RONG;
//                log.info("Sanh rong");
//                break;
//            }
//            /**
//             * 6 đôi
//             */
//            if ((fourthList.size() + secondList.size()) == 6) {
//                firstPlayerIndex = playerIndex;
//                immediateWin = true;
//                winType=CardConstant.AN_TRANG_6_DOI;
//                log.info("6 doi");
//                break;
//            }
//            /**
//             * Ván đầu tiên,có 3 đôi thông 3-4-5 và 3 bích
//             */
//            if( (secondList.size() >=3) && ((Integer)secondList.get(0) == (Integer)(gt.cards[playerIndex][0]/4)) && gt.isNewTurn)
//            {
//
//                boolean flag = true;
//                if(gt.cards[playerIndex][0]!=12){
//                    flag=false;
//                }
//                for (int i = 1; i <= 2; i++){
//                    if ((Integer)secondList.get(i) - (Integer)secondList.get(i - 1) != 1){
//                        flag = false;
//                    }
//                }
//                if(flag){
//                    firstPlayerIndex = playerIndex;
//                    log.info("3 doi thong 3-4-5 co 3 bich");
//                    immediateWin = true;
//                    winType=CardConstant.AN_TRANG_3_DOI_THONG_3_BICH;
//                    break;
//                }
//            }
//            /**
//             * 5 đôi thông
//             */
//             if (secondList.size() == 5)
//            {
//                boolean flag = true;
//                for (int i = 1; i < secondList.size(); i++){
//                    if (((Integer)secondList.get(i) - (Integer)secondList.get(i - 1)) != 1){
//                         flag = false;
//                    }
//                }
//                 if(flag){
//                    firstPlayerIndex = playerIndex;
//                    immediateWin = true;
//                    winType=CardConstant.AN_TRANG_5_DOI_THONG;
//                    log.info("5 doi thong");
//                    break;
//                }
//            }
//            }
//        }
//
//        if (immediateWin) {
//            gt.playerResult[0] = gt.getJoinedPlayerAt(firstPlayerIndex);
//            gt.playerBalance[0] = +(gt.betMoney*2)*(gt.getNumberOfJoinedPlayers()-1);
//            int i = 1;
//            for (int playerIndex = 0; playerIndex < gt.getNumberOfJoinedPlayers(); playerIndex++) {
//                if (playerIndex != firstPlayerIndex) {
//                     gt.playerResult[i] = gt.getJoinedPlayerAt(playerIndex);
//                     gt.playerBalance[i] = -gt.betMoney*2;
//                     i++;
//                }
//            }
//        }
//        return winType;
//    }

    // hanv: lập danh sách úng heo/hàng của player ứng với playerJoined
    // trả về true nếu có úng
    public boolean setPlayerUngList(GameTable gt,int playerIndex) {

        for (int i=0; i<gt.ungHangList[playerIndex].length; i++) {
            gt.ungHangList[playerIndex][i] = 0;
        }

        for (int i = 0; i < gt.cards[playerIndex].length; i++) {
            //Úng heo đen
            if( (gt.cards[playerIndex][i]==60)||(gt.cards[playerIndex][i]==61) ){
                gt.ungHangList[playerIndex][CardConstant.UNG_HEODEN]++;
            }
            //Úng heo đỏ
            if( (gt.cards[playerIndex][i]==62)||(gt.cards[playerIndex][i]==63) ){
                gt.ungHangList[playerIndex][CardConstant.UNG_HEODO]++;
            }
            //Úng ba bích - hanv
            if (gt.cards[playerIndex][i] == 12) {
                gt.ungHangList[playerIndex][CardConstant.UNG_BABICH] = 1;
            } else if (gt.cards[playerIndex][i] > 12) {
                gt.ungHangList[playerIndex][CardConstant.UNG_BABICH] = 0;
            }
        }

        ArrayList firstList = new ArrayList();
        ArrayList secondList = new ArrayList();
        ArrayList thirdList = new ArrayList();
        ArrayList fourthList = new ArrayList();
        for (int i = 0; i < gt.cards[playerIndex].length; i++){
            // Khong tinh nhung la bai da di roi
            // hanv: 3,4 doi thong chi toi A
            if (gt.cards[playerIndex][i] != 0 && gt.cards[playerIndex][i] < 60) {
                if (firstList.contains(gt.cards[playerIndex][i]/4)) {
                    if (secondList.contains(gt.cards[playerIndex][i]/4)) {
                        if (thirdList.contains(gt.cards[playerIndex][i]/4)) {
                            fourthList.add(gt.cards[playerIndex][i]/4);
                        } else {
                            thirdList.add(gt.cards[playerIndex][i]/4);
                        }
                    } else {
                        secondList.add(gt.cards[playerIndex][i]/4);
                    }
                } else {
                    firstList.add(gt.cards[playerIndex][i]/4);
                }
            }
        }

        boolean badoithong = false;
        boolean bondoithong = false;
        int tuqui = fourthList.size();
        int count = 0;
        for (int i = 1; i < secondList.size(); i++) {
            if((Integer)secondList.get(i) - (Integer)secondList.get(i - 1) == 1)
                count++;
            else
                count = 0;
            if (count == 2) {
                if (!((tuqui != 0) &&
                    (fourthList.contains(secondList.get(i - 2)) ||
                    fourthList.contains(secondList.get(i - 1)) ||
                    fourthList.contains(secondList.get(i)))))
                    badoithong = true;
            }
            if (count == 3) {
                bondoithong = true;
                badoithong = false;
            }
        }

        if (badoithong) {
            gt.ungHangList[playerIndex][CardConstant.UNG_BADOITHONG]++;
        }

        if (bondoithong) {
            gt.ungHangList[playerIndex][CardConstant.UNG_BONDOITHONG]++;
        } else if (tuqui != 0) {
            gt.ungHangList[playerIndex][CardConstant.UNG_TUQUY]++;
        }

        for (int i=0; i<gt.ungHangList[playerIndex].length; i++) {
            if (gt.ungHangList[playerIndex][i] > 0)
                return true;
        }
        return false;
    }

    public int getMoneyUngDoChoi(GameTable gt,int playerIndex){
        int money=0;
        /**
         * úng heo
         */

        for (int i = 0; i < gt.cards[playerIndex].length; i++) {
            //Úng heo đen
            if( (gt.cards[playerIndex][i]==60)||(gt.cards[playerIndex][i]==61) ){
                 money += gt.betMoney/2;
                 gt.ungHangList[playerIndex][CardConstant.UNG_HEODEN]++;
                 TienLenService.logGame.debug(gt.tableID+": "+ gt.getJoinedPlayerAt(playerIndex)+" ung heo den. Phat: "+gt.betMoney/2);
            }
            //Úng heo đỏ
            if( (gt.cards[playerIndex][i]==62)||(gt.cards[playerIndex][i]==63) ){
                money += gt.betMoney;
                gt.ungHangList[playerIndex][CardConstant.UNG_HEODO]++;
                TienLenService.logGame.debug(gt.tableID+": "+gt.getJoinedPlayerAt(playerIndex)+" ung heo do. Phat: "+gt.betMoney);
            }
            //Úng ba bích - hanv
            if (gt.cards[playerIndex][i] == 12) {
                gt.ungHangList[playerIndex][CardConstant.UNG_BABICH] = 1;
            } else if (gt.cards[playerIndex][i] > 12) {
                gt.ungHangList[playerIndex][CardConstant.UNG_BABICH] = 0;
            }
        }

        if (gt.ungHangList[playerIndex][CardConstant.UNG_BABICH] == 1) {
            money += gt.betMoney;
        }
        /**
         * úng 3 đôi thông,tứ quý
         */
        ArrayList firstList = new ArrayList();
        ArrayList secondList = new ArrayList();
        ArrayList thirdList = new ArrayList();
        ArrayList fourthList = new ArrayList();
        for (int i = 0; i < gt.cards[playerIndex].length; i++){
            //Khong tinh nhung la bai da di roi
            if(gt.cards[playerIndex][i]!=0){
                if (firstList.contains(gt.cards[playerIndex][i]/4))
                {
                    if (secondList.contains(gt.cards[playerIndex][i]/4))
                    {
                        if (thirdList.contains(gt.cards[playerIndex][i]/4))
                        {
                            fourthList.add(gt.cards[playerIndex][i]/4);
                        }
                        else
                        {
                            thirdList.add(gt.cards[playerIndex][i]/4);
                        }
                    }
                    else
                    {
                        secondList.add(gt.cards[playerIndex][i]/4);
                    }
                }
                else
                {
                    firstList.add(gt.cards[playerIndex][i]/4);
                }
           }
        }

       /*
            for(int i = 0; i < firstList.size(); i++)
              log.info("First"+ firstList.get( i ) );
            for(int i = 0; i < secondList.size() ; i++)
              log.info("secondList"+ secondList.get( i ) );

            for(int i = 0; i < thirdList.size() ; i++)
              log.info("thirdList"+ thirdList.get( i ) );
            for(int i = 0; i < fourthList.size() ; i++)
              log.info("fourthList"+ fourthList.get( i ) );*/

        boolean badoithong = false;
        boolean bondoithong = false;
        int tuqui = fourthList.size();
        int count = 0;
        for (int i = 1; i < secondList.size(); i++) {
            if((Integer)secondList.get(i) - (Integer)secondList.get(i - 1) == 1)
                count++;
            else
                count = 0;
            if (count == 2) {
                if (!((tuqui != 0) &&
                    (fourthList.contains(secondList.get(i - 2)) ||
                    fourthList.contains(secondList.get(i - 1)) ||
                    fourthList.contains(secondList.get(i)))))
                    badoithong = true;
            }
            if (count == 3) {
                bondoithong = true;
                badoithong = false;
            }
        }
        if(badoithong) {
            money += gt.betMoney;
            gt.ungHangList[playerIndex][CardConstant.UNG_BADOITHONG]++;
            TienLenService.logGame.debug(gt.tableID+": "+gt.getJoinedPlayerAt(playerIndex)+" ung 3 doi thong bi phat "+money);
        }
        if (bondoithong) {
            money += 2*gt.betMoney;
            gt.ungHangList[playerIndex][CardConstant.UNG_BONDOITHONG]++;
            TienLenService.logGame.debug(gt.tableID+": "+gt.getJoinedPlayerAt(playerIndex)+" ung bon doi thong bi phat "+money);
        } else if (tuqui != 0) {
            money += tuqui * gt.betMoney * 1.5;
            gt.ungHangList[playerIndex][CardConstant.UNG_TUQUY]++;
            TienLenService.logGame.debug(gt.tableID+": "+gt.getJoinedPlayerAt(playerIndex)+" ung tu qui bi phat "+money);
        }
        return money;
    }

    public boolean checkMove(byte[] cards, GameTable gt, byte playerIndex) {

        boolean result = false;

        // kiem tra bai gui len client co chinh xac khong
        if (!checkCardOwnership(cards, gt, playerIndex)) {
            TienLenService.logGame.warn(gt.tableID+": "+"Cards not existed from "+gt.getJoinedPlayerAt(playerIndex));
            return false;
        }
        TienLenService.logGame.debug("{}: Cards OK",gt.tableID);

        // kiem tra 3 bich (hoac quan be nhat) trong lan chia dau tien & danh dau tien
        if (gt.isFirstDeal && gt.isNewTurn) {
            if (cards[0] != gt.cards[playerIndex][0]) {
                TienLenService.logGame.debug(gt.tableID+": "+"Min card is required");
                return false;
            }
            /*
            byte minCard=63;
            for(int i=0;i<13;i++)
            {
                if(minCard>gt.cards[playerIndex][i]){
                    minCard=gt.cards[playerIndex][i];
                }
            }
            if (cards[0] != minCard) {
                log.info("Min card is required");
                return false;
            }
             *
             */
            gt.isFirstDeal = false;
        }

        byte moveType = getCardPlayType(cards);
        result = moveType != CardConstant.MOVE_INVALID;
        if (result){
            if (!gt.isNewTurn){
                result = isGreaterThanOpponent(moveType, cards, gt.lastMoveType, gt.lastPlayedCards);
            }
            if(gt.isNewTurn||result){
//                if (gt.lastTurnPlayer != -1 && gt.noCardsLeft[gt.lastTurnPlayer] != 0)  // hanv - fix bug chat heo cuoi
                    setPenaltyMoney(moveType, cards, playerIndex, gt.lastTurnPlayer, gt);
            }
            gt.lastMoveType = moveType;
            gt.lastPlayedCards = cards;
            gt.isNewTurn = false;
        }
        return result;
    }

    // kiem tra Doi
    public static boolean checkAPair(byte[] arr) {
//        TienLenService.logGame.debug(" checkAPair");
        if (arr.length == 2) {
            if (CardUtils.getCardValue(arr[0]) == CardUtils.getCardValue(arr[1])) {
                return true;
            }
        }
        return false;
    }

    public static int getNumberHeoDo(byte[][] arr){
        int number=0;
        for(int i=0;i<arr.length;i++){
            if(arr[i]!=null){
                for(int j=0; j<arr[i].length;j++){
                    if( (arr[i][j]==62)||(arr[i][j]==63))  number++;
                }
            }
        }
        return number;
    }

    public static int getNumberHeoDen(byte[][] arr){
        int number=0;
        for(int i=0;i<arr.length;i++){
           if(arr[i]!=null){
               for(int j=0; j<arr[i].length;j++){
                    if( (arr[i][j]==60)||(arr[i][j]==61)) number++;
               }
            }
        }
        return number;
    }

    public static int getNumberFourOfAKind(byte[][] arr){
        int number=0;
        for(int i=0;i<arr.length;i++){
           if(arr[i]!=null){
               if(checkFourOfAKind(arr[i])){
                number++;
               }
            }
        }
        return number;
    }


    public static int getNumberThreeDoubleContiguous(byte[][] arr){
        return 0;
    }


    // kiem tra Tam Co
    public static boolean checkThreeOfAKind(byte[] arr) {
//        TienLenService.logGame.debug("checkThreeOfAKind");
        if (arr.length == 3) {
            if ((CardUtils.getCardValue(arr[0]) == CardUtils.getCardValue(arr[1]))
                    && (CardUtils.getCardValue(arr[1]) == CardUtils.getCardValue(arr[2]))) {
                return true;
            }
        }

        return false;
    }

    // check if the array is contiguous (sanh)
    public static boolean checkContiguousArray(byte[] arr) {
//        TienLenService.logGame.debug("checkContiguousArray");
        boolean result = true;

        if (CardUtils.getCardValue(arr[arr.length - 1]) == 15) {
            result = false;
        } else {
            int i = 0;
            while (i < arr.length - 1) {
                if (CardUtils.getCardValue(arr[i + 1]) - 1 != CardUtils.getCardValue(arr[i])) {
                    result = false;
                    break;
                }
                i++;
            }
        }



        return result;
    }

    // kiem tra Tu qui
    public static boolean checkFourOfAKind(byte[] arr) {
//        TienLenService.logGame.debug("checkFourOfAKind");
        boolean result = false;

        if (arr.length == 4) {
            if ((CardUtils.getCardValue(arr[0]) == CardUtils.getCardValue(arr[1]))
                    && (CardUtils.getCardValue(arr[2]) == CardUtils.getCardValue(arr[3]))
                    && (CardUtils.getCardValue(arr[0]) == CardUtils.getCardValue(arr[2]))) {
                result = true;
            }
        }

        return result;
    }

    // check if the array has two contiguous sub-arrays (doi thong)
    public static boolean checkDoubleContiguousArray(byte[] arr) {
//        TienLenService.logGame.debug("checkDoubleContiguousArray");
        boolean result = false;

        if (arr.length % 2 == 0) {
            int subArrLength = arr.length >> 1;
            byte[] arr1 = new byte[subArrLength];
            byte[] arr2 = new byte[subArrLength];

            for (int i = 0; i < subArrLength; i++) {
                arr1[i] = arr[i * 2];
                arr2[i] = arr[1 + i * 2];
            }

            if (checkContiguousArray(arr1) && checkContiguousArray(arr2)
                    && (CardUtils.getCardValue(arr1[0]) == CardUtils.getCardValue(arr2[0]))) {
                result = true;
            }
        }

        return result;
    }

    public byte getCardPlayType(byte[] cards) {
        boolean result = false;
        byte moveType = CardConstant.MOVE_INVALID;
//        log.debug("Played {} card(s)\n", cards.length);
        switch (cards.length) {
            case 1:
                moveType = CardConstant.MOVE_SINGLE;
                result = true;
                break;
            case 2:
                result = checkAPair(cards);
                if (result) {
                    moveType = CardConstant.MOVE_DOI;
                }
                break;
            default:
                result = checkContiguousArray(cards);
                if (result) {
                    moveType = CardConstant.MOVE_SANH;
                } else {
                    switch (cards.length) {
                        case 3: // TAM CO
                            result = checkThreeOfAKind(cards);
                            if (result) {
                                moveType = CardConstant.MOVE_TAMCO;
                            }
                            break;
                        case 4: // TU QUI
                            result = checkFourOfAKind(cards);
                            if (result) {
                                moveType = CardConstant.MOVE_TUQUI;
                            }
                            break;
                        case 6: // 3 DOI THONG
                            result = checkDoubleContiguousArray(cards);
                            if (result) {
                                moveType = CardConstant.MOVE_BADOITHONG;
                            }
                            break;
                        case 8: // 4 DOI THONG
                            result = checkDoubleContiguousArray(cards);
                            if (result) {
                                moveType = CardConstant.MOVE_BONDOITHONG;
                            }
                            break;
                        default:
                            break;
                    } // switch
                } // end if

        }// end switch
        return moveType;
    }

    private static boolean isGreaterThanOpponent(int myMoveType,
                                                 byte[] myCards,
                                                 int yourMoveType,
                                                 byte[] yourCards ) {
        boolean result = false;
        if (myMoveType == yourMoveType){
            if (myCards.length == yourCards.length
                    && myCards[myCards.length - 1] > yourCards[yourCards.length - 1]) {
                result = true;
            }
        }
        // opponent plays one pig
        else if(((yourCards.length == 1) && (CardUtils.getCardValue(yourCards[0]) == CardConstant.PIG))
                &&
                (myMoveType == CardConstant.MOVE_BADOITHONG
                || myMoveType == CardConstant.MOVE_TUQUI
                || myMoveType == CardConstant.MOVE_BONDOITHONG)
            ){
                result = true;
        }
        // opponent plays a pair of pig
        else if(((yourCards.length == 2) && (CardUtils.getCardValue(yourCards[0]) == CardConstant.PIG))
                    &&(myMoveType == CardConstant.MOVE_TUQUI || myMoveType == CardConstant.MOVE_BONDOITHONG))
        {
                result = true;
        }
         // opponent plays 3 doi thong
        else if (yourMoveType == CardConstant.MOVE_BADOITHONG
                && (myMoveType == CardConstant.MOVE_BONDOITHONG || myMoveType == CardConstant.MOVE_TUQUI)) {
            result = true;
        } // opponent plays four of a kind
        else if (yourMoveType == CardConstant.MOVE_TUQUI
                && myMoveType == CardConstant.MOVE_BONDOITHONG) {
            result = true;
        }
        return result;
    }// end if

    public boolean findNextTurnPlayer(GameTable gt, byte curPlayerIndex) {
        /*
         * Tim nguoi choi ke tiep (ke tu curPlayerIndex) voi cac dieu kien
         *  - co trong danh sach tham gia choi
         *  - chua bo luot
         *  - co uu tien - priority (co do choi nhu 4 doi thong)
         *  - chua danh het bai
         */

        boolean result = false;

        byte pIndex = curPlayerIndex;
        int noUsers = gt.getNumberOfJoinedPlayers();

        // count users who bypassed turns
        int playerInTurnCount = gt.countTurnMembers();

        for (byte playerCounter = 0; playerCounter < noUsers; playerCounter++) {
            pIndex = (byte) ((pIndex + 1) % noUsers);
            //Neu la heo,tu quy,3 doi thong hoac doi heo thi nguoi co 4 doi thong dc uu tien
            if (gt.lastPlayedCards != null) {
                if (CardUtils.getCardValue(gt.lastPlayedCards[gt.lastPlayedCards.length - 1]) == CardConstant.PIG) {
                    if ((gt.lastPlayedCards.length == 1) || (gt.lastPlayedCards.length == 2)) {
                        if (isContainBonDoiThong(gt, pIndex)) {
                            TienLenService.logGame.debug(gt.getJoinedPlayerAt(pIndex) + " co 4 doi thong,duoc uu tien");
                            //gt.playerWithTurnPriority[pIndex]=true;
                            gt.playerBypassedTurn[pIndex] = false;
                        }
                    }
                }
            }
            // DIEU KIEN:
            // - player chua mat luot hoac co do choi (4 doi thong)
            // - player van con bai
            // - player chua bi chet cong
            // - player chua thoat ngang    - hanv add
            String player = gt.getJoinedPlayerAt(pIndex);   // hanv add
            if (((!gt.playerBypassedTurn[pIndex]) || (gt.playerWithTurnPriority[pIndex]))
                    && (gt.noCardsLeft[pIndex] > 0)
                    && (!gt.playerCongBai.contains(player))
                    && (!gt.playerThoatNgang.contains(player))) {   // hanv add
                gt.nextTurnPlayer = pIndex;

                // new nguoi choi truoc cung la nguoi danh duy nhat trong luot
                // thi reset lai thanh luot choi moi
//                if ((gt.lastTurnPlayer==pIndex) && (playerInTurnCount==1)) {
                    //gt.resetTurn();
//                    log.info(gt.tableID+": Should be reset turn here");
//                }
//                if (((pIndex==gt.lastTurnPlayer)||(pIndex==curPlayerIndex))
//                        &&(playerInTurnCount==1)) {
//                //if ((playerInTurnCount==1)&&(gt.noCardsLeft[gt.lastTurnPlayer]>0)) {
//                    //gt.resetTurn();
//                }

                // sau khi la nguoi duy nhat bat bai nguoi toi nhat
                // nguoi ket thuc luot cu duoc di tiep
//                if ((pIndex==curPlayerIndex) && gt.isHuongSaiTurn
//                        && (playerInTurnCount==1)) {
//                    gt.resetTurn();
//                }

                result = true;
                break;
            }
        }

        return result;
    }

    public boolean isContainBonDoiThong(GameTable gt,int playerIndex) {
        ArrayList firstList = new ArrayList();
        ArrayList secondList = new ArrayList();
        ArrayList thirdList = new ArrayList();
        ArrayList fourthList = new ArrayList();
        for (int i = 0; i < gt.cards[playerIndex].length; i++){
            //Khong tinh nhung la bai da di roi
            if(gt.cards[playerIndex][i]!=0){
                if (firstList.contains(gt.cards[playerIndex][i]/4))
                {
                    if (secondList.contains(gt.cards[playerIndex][i]/4))
                    {
                        if (thirdList.contains(gt.cards[playerIndex][i]/4))
                        {
                            fourthList.add(gt.cards[playerIndex][i]/4);
                        }
                        else
                        {
                            thirdList.add(gt.cards[playerIndex][i]/4);
                        }
                    }
                    else
                    {
                        secondList.add(gt.cards[playerIndex][i]/4);
                    }
                }
                else
                {
                    firstList.add(gt.cards[playerIndex][i]/4);
                }
           }
        }
        int count = 0;
        for (int i = 1; i < secondList.size(); i++)
        {
            if((Integer)secondList.get(i) - (Integer)secondList.get(i - 1) == 1)
                count++;
            else
                count = 0;
            if (count == 3)
            {
                return true;//4 doi thong
            }
        }
        return false;
    }

    public void setPenaltyMoney( int movetype,byte[] cards,byte myIndex,byte yourIndex,GameTable gt){
         /**
         * Nếu trong danh sách cũ có heo thì chặt đè
         */
        if(movetype==CardConstant.MOVE_BADOITHONG ||
                movetype==CardConstant.MOVE_BONDOITHONG ||
                movetype==CardConstant.MOVE_TUQUI) {
            int money=0;
            /**
            if( (gt.chatChongList.contains(CardConstant.MOVE_SINGLE_HEODEN))||(gt.chatChongList.contains(CardConstant.MOVE_SINGLE_HEODO))){

            }
             **/
            /**
             * Vẫn bị chặt hàng nếu ko có heo trong list
             */
            for(int n=0;n<gt.chatChongList.size();n++){
                    switch( (Integer)gt.chatChongList.get(n)){
                        case CardConstant.MOVE_SINGLE_HEODEN:
                            money += gt.betMoney/2;
                            break;
                        case CardConstant.MOVE_SINGLE_HEODO:
                            money += gt.betMoney;
                            break;
                        case CardConstant.MOVE_DOI_DENDEN:
                            money += gt.betMoney;
                            break;
                        case CardConstant.MOVE_DOI_DENDO:
                            money += gt.betMoney*(1.5);
                            break;
                        case CardConstant.MOVE_DOI_DODO:
                            money += gt.betMoney*2;
                            break;
                        case CardConstant.MOVE_TUQUI:
                            money += gt.betMoney*(1.5);
                            break;
                        case CardConstant.MOVE_BADOITHONG:
                            money += gt.betMoney;
                            break;
                        case CardConstant.MOVE_BONDOITHONG:
                            money += gt.betMoney*2;
                            break;
                        default:
                            money+=0;
                            break;
                    }
                }
            if(money>0){
                gt.nguoiBiChat=(String)gt.getJoinedPlayerAt(yourIndex);
                gt.nguoiChat  =(String)gt.getJoinedPlayerAt(myIndex);
                gt.soTienChat =money;
            }
        }
        /**
         * Lưu vào log để chặt sau này
         */
        int logMoveType=movetype;
        if(movetype==CardConstant.MOVE_SINGLE){
            if( (cards[0]==60)||(cards[0]==61) ){
               logMoveType=CardConstant.MOVE_SINGLE_HEODEN;
            }
            if( (cards[0]==62)||(cards[0]==63) ){
                logMoveType=CardConstant.MOVE_SINGLE_HEODO;
            }
        }else if(movetype==CardConstant.MOVE_DOI){
            if( ((cards[0]==60)&&(cards[1]==61))||((cards[0]==61)&&(cards[1]==60)) ){
               logMoveType=CardConstant.MOVE_DOI_DENDEN;
            }else if( ((cards[0]==62)&&(cards[1]==63))||((cards[0]==63)&&(cards[1]==62)) ){
                logMoveType=CardConstant.MOVE_DOI_DODO;
            }else if( ((cards[0]==60)||(cards[0]==61))&&((cards[1]==62)||(cards[1]==63)) ){
                logMoveType=CardConstant.MOVE_DOI_DENDO;
            }
        }

        switch (logMoveType) {
            case CardConstant.MOVE_BADOITHONG:
            case CardConstant.MOVE_BONDOITHONG:
            case CardConstant.MOVE_TUQUI:
            case CardConstant.MOVE_SINGLE_HEODEN:
            case CardConstant.MOVE_SINGLE_HEODO:
            case CardConstant.MOVE_DOI_DENDEN:
            case CardConstant.MOVE_DOI_DENDO:
            case CardConstant.MOVE_DOI_DODO:
                gt.chatChongList.add(logMoveType);
            default:
        }
        //gt.chatChongList.add(gt.chatChongIndex,logMoveType);
        //gt.chatChongIndex++;
    }

}
